#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 程序功能: 按关键字爬取微博清单
import os
import re  # 正则表达式提取文本
from jsonpath import jsonpath  # 解析json数据
import requests  # 发送请求
import pandas as pd  # 存取csv文件
import datetime  # 转换时间用
import json
from time import sleep
import random
import logging
import logging.config #weibo加载配置
import csv
import schedule
import time
import pymysql


# 请求头
headers = {
	"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Mobile Safari/537.36",
	"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
	"accept-encoding": "gzip, deflate, br",
}


def trans_time(v_str):
	"""转换GMT时间为标准格式"""
	GMT_FORMAT = '%a %b %d %H:%M:%S +0800 %Y'
	timeArray = datetime.datetime.strptime(v_str, GMT_FORMAT)
	ret_time = timeArray.strftime("%Y-%m-%d %H:%M:%S")
	return ret_time


def getLongText(v_id):
	"""爬取长微博全文"""
	url = 'https://m.weibo.cn/statuses/extend?id=' + str(v_id)
	r = requests.get(url, headers=headers)
	# r = demjson.encode(r, encoding='utf-8')
	json_data = r.json()
	long_text = json_data['data']['longTextContent']
	# 微博内容-正则表达式数据清洗
	dr = re.compile(r'<[^>]+>', re.S)
	long_text2 = dr.sub('', long_text)
	# print(long_text2)
	return long_text2


def get_weibo_list(v_keyword, v_max_page, v_weibo_file, v_weibo_json, mysql_weibo_author_id_list):
	"""
	爬取微博内容列表
	:param v_keyword: 搜索关键字
	:param v_max_page: 爬取前几页
	:return: None
	"""
	global a
	jss = []
	user_count1 = random.randint(6, 10)
	for page in range(0, v_max_page + 1):

		print('===开始爬取第{}页微博==='.format(page))
		# 请求地址
		url = 'https://m.weibo.cn/api/container/getIndex'
		# 请求参数
		params = {
			"containerid": "100103type=61&q={}".format(v_keyword),
			"page_type": "searchall",
			"page": page
		}

		if (a == 10): break

		# # 发送请求
		# r = requests.get(url, headers=headers, params=params)
		# print(r.status_code)
		# # print(r.json())
		# # 解析json数据
		# cards = r.json()["data"]["cards"]

		try:
			# 发送请求
			r = requests.get(url, headers=headers, params=params)
			r.raise_for_status()  # 检查请求是否成功，如果失败则抛出异常
			print(r.status_code)

			# 解析json数据
			data = r.json().get("data", {})
			cards = data.get("cards", [])

			if not cards:
				print('未获取到微博内容，进入下一轮循环')
				a+=1
				continue

		# 其他解析和处理逻辑...

		except requests.exceptions.RequestException as e:
			print('请求异常:', e)



		# 微博内容
		text_list = jsonpath(cards, '$..mblog.text')#..可以理解为递归搜索
		# 微博内容-正则表达式数据清洗
		dr = re.compile(r'<[^>]+>', re.S)
		text2_list = []
		# print('text_list is:')
		# print(text_list)
		if not text_list:  # 如果未获取到微博内容，进入下一轮循环
			continue
		if type(text_list) == list and len(text_list) > 0:
			for text in text_list:
				text2 = dr.sub('', text)  # 正则表达式提取微博内容
				# print(text2)
				text2_list.append(text2)
		# 微博创建时间
		time_list = jsonpath(cards, '$..mblog.created_at')
		time_list = [trans_time(v_str=i) for i in time_list]
		# 微博作者
		author_list = jsonpath(cards, '$..mblog.user.screen_name')
		# 微博作者id
		author_id_list = jsonpath(cards, '$..mblog.user.id')



		# 微博发布地址
		location_list = []
		region=''
		location_list_length = len(author_id_list)
		for cardsi in cards:
			if 'region_name' in cardsi['mblog'].keys():
				location_list.append(cardsi['mblog']['region_name'])
			else:
				location_list.append(region)
		# 微博id
		id_list = jsonpath(cards, '$..mblog.id')
		# 判断是否存在全文
		# 判断是否存在全文
		isLongText_list = jsonpath(cards, '$..mblog.isLongText')
		idx = 0
		for i in isLongText_list:
			if i == True:
				long_text = getLongText(v_id=id_list[idx])
				text2_list[idx] = long_text
			idx += 1
		# 转发数
		reposts_count_list = jsonpath(cards, '$..mblog.reposts_count')
		# 评论数
		comments_count_list = jsonpath(cards, '$..mblog.comments_count')
		# 点赞数
		attitudes_count_list = jsonpath(cards, '$..mblog.attitudes_count')
		#链接
		Weblink_list=[]
		lengthid_list=len(id_list)
		detail='https://m.weibo.cn/detail/'
		for i in range(0, lengthid_list):
			Weblink_list.append(detail+id_list[i])
		#搜索关键字
		v_keyword_list=[]
		for i in range(0, lengthid_list):
			v_keyword_list.append(v_keyword)
		# 把列表数据保存成DataFrame数据
		df = pd.DataFrame(
			{
				'搜索关键字': v_keyword_list,
				'页码': [page] * len(id_list),
				'微博id': id_list,
				'微博作者': author_list,
				'发布时间': time_list,
				'微博内容': text2_list,
				'转发数': reposts_count_list,
				'评论数': comments_count_list,
				'点赞数': attitudes_count_list,
				'网页链接': Weblink_list,
				'作者id': author_id_list,
				'发布地址': location_list
			}
		)

		if os.path.exists(v_weibo_file):
			header = None
		else:
			header = ['搜索关键字', '页码', '微博id', '微博作者', '发布时间', '微博内容', '转发数', '评论数', '点赞数', '网页链接','作者id','发布地址']  # csv文件头
		# 保存到csv文件
		df.to_csv(v_weibo_file, mode='a+', index=False, header=header, encoding='utf_8_sig')
		print('csv保存成功:{}'.format(v_weibo_file))



def one_search(search_keyword, jsontxt, csvpath, max_search_page):

	# 调用爬取微博函数
	weibo_author_id_list = []
	get_weibo_list(v_keyword=search_keyword, v_max_page=max_search_page, v_weibo_file=csvpath, v_weibo_json=jsontxt, mysql_weibo_author_id_list=weibo_author_id_list)
	# 数据清洗-去重
	pdpath=""+csvpath+""
	df = pd.read_csv(pdpath)
	# 删除重复数据
	df.drop_duplicates(subset=['微博id'], inplace=True, keep='first')
	# 再次保存csv文件
	df.to_csv(pdpath, index=False, encoding='utf_8_sig')
	print('数据清洗完成')

def mysql_create(csvfile):
	connect = pymysql.connect(host='182.92.243.168',  # 本地数据库 学校的舆情系统数据库这里写10.119.130.183就可以
							  port=3307,  # 本地数据库端口  学校的端口为3306
							  user='root',  # 你自己的数据库  学校的为root
							  password='1234',  # 修改成你自己的数据库密码  学校的为mwyq912
							  db='weibo',  # 数据库名称 没有可以不填写  学校的为mwyq_db
							  charset='utf8mb4')  # 服务器名,账户,密码，数据库名称
	cur = connect.cursor()
	# 创建'weibo_keywords'表
	create_table = """
	                CREATE TABLE IF NOT EXISTS weibo_keywords (
	                weibo_id varchar(20) NOT NULL,
	                author_name varchar(30),
	                create_time DATETIME,
	                content varchar(500),
	                article_url varchar(200),
	                like_count INT,
	                comment_count INT,
	                transmit_count INT,
	                keywords varchar(200),
	                sentiment INT,
	                stance INT,
	                PRIMARY KEY (weibo_id)
	                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"""
	#InnoDB：数据库默认的存储引擎，处理大容量数据。
    #删除表时：InnoDB不会重新建立表，而是一行一行的删除 会在内存中缓冲数据和索引，但是不支持fulltext的索引
	#数据库默认编码为utf8mb4
	cur.execute(create_table)

	table_name ="weibo_keywords"
	# 显示表的结构
	sql = 'desc {}'.format(table_name)
	cur.execute(sql)
	# print("显示表的结构：", cur.fetchall())

def mysql_write(csvfile):
	# connect = pymysql.connect(host='localhost',  # 本地数据库 学校的舆情系统数据库这里写10.119.130.183就可以
	# 						  port=3306,  # 本地数据库端口  学校的端口为3306
	# 						  user='root',  # 你自己的数据库  学校的为root
	# 						  password='root',  # 修改成你自己的数据库密码  学校的为mwyq912
	# 						  db='mwyq_db',  # 数据库名称 没有可以不填写  学校的为mwyq_db
	# 						  charset='utf8mb4')  # 服务器名,账户,密码，数据库名称
	connect = pymysql.connect(host='10.119.130.183',  # 本地数据库 学校的舆情系统数据库这里写10.119.130.183就可以
							  port=3306,  # 本地数据库端口  学校的端口为3306
							  user='root',  # 你自己的数据库  学校的为root
							  password='mwyq912',  # 修改成你自己的数据库密码  学校的为mwyq912
							  db='mwyq_db',  # 数据库名称 没有可以不填写  学校的为mwyq_db
							  charset='utf8mb4')  # 服务器名,账户,密码，数据库名称
	cur = connect.cursor()
	sql = "SELECT * FROM weibo"
	response1 = cur.execute(sql)
	response = cur.fetchall()
	weibo_id_list = []
	kflag = 0
	for row in response:
		if kflag==0:
			continue
		weibo_id = row[0]  # <class 'str'>
		weibo_id_list.append(weibo_id)
		kflag = kflag + 1
	numbers = csv.DictReader(csvfile)
	for row in numbers:
		if row['微博id'] not in weibo_id_list:
			try:
				tempkeywords= row['\ufeff搜索关键字']
				sql="INSERT INTO weibo(id,author_name,create_time,content,article_url,like_count,comment_count,transmit_count,Queryword,sentiment,author_id, location) values('"+str(row['微博id'])+"','"+str(row['微博作者'])+"','"+row['发布时间']+"','"+str(row['微博内容'])+"','"+str(row['网页链接'])+"','"+row['点赞数']+"','"+row['评论数']+"','"+row['转发数']+"','"+str(tempkeywords)+"',"+"NULL"+",'"+str(row['作者id'])+"','"+str(row['发布地址'])+"')"
				# sql="INSERT INTO weibo_keywords(weibo_id,author_name,content,article_url,like_count,comment_count,transmit_count) values('"+str(row['微博id'])+"','"+str(row['微博作者'])+"','"+str(row['微博内容'])+"','"+str(row['网页链接'])+"','"+row['点赞数']+"','"+row['评论数']+"','"+row['转发数']+"','"+str(tempkeywords)+"')"
				# print(sql)
				cur.execute(sql)
				connect.commit()
				weibo_id_list.append(row['微博id'])
			except:
				# 如果发生错误则回滚
				connect.rollback()

def spider():
	jsontxt = os.path.split(
		os.path.realpath(__file__))[0] + os.sep + 'weibo_allsearch_npages.json'

	csvpath = os.path.split(
		os.path.realpath(__file__))[0] + os.sep + 'weibo_allsearch_npages.csv'


	keywords_list_path = os.path.split(
		os.path.realpath(__file__))[0] + os.sep + 'keywords_list.txt'

	all_search_keyword = []

	with open(keywords_list_path, 'rb') as f:
		lines = f.read().splitlines()
		lines = [line.decode('utf-8-sig') for line in lines]
		for line in lines:
			# info = line.split(' ')
			all_search_keyword.append(line)
	# all_search_keyword=['语言文字', '汉字', '普通话', '二十大', '语信司', '国家语委', '拼音', '藏语', '蒙语', '维语','字母o','国家语言委员会','方言','粤语','简体字']
	# all_search_keyword = ['语言文字']
	max_search_page = 2000  # 页数设置只要能爬取的够当天的全部能下来就行
	for i in all_search_keyword:
		one_search(i, jsontxt, csvpath, max_search_page)  # 最后一个变量为爬取页数
	# with open(v_weibo_json, "w", encoding='utf-8') as fp:
	csvfile = open(csvpath, 'r', encoding='utf-8')
	all_numbers = 0
	j = 0
	with open(jsontxt, 'w', encoding='utf-8') as jsonfile:
		jsonfile.write("[")
		numbers = csv.DictReader(csvfile)  # 以字典形式读取
		for u in numbers:
			all_numbers += 1
		# print(all_numbers)
		all_numbers = all_numbers - 1
		csvfile.close()
		csvfile = open(csvpath, 'r', encoding='utf-8')
		numbers = csv.DictReader(csvfile)  # 以字典形式读取
		for i in numbers:
			d = {}
			for k, v in i.items():
				d[k] = v
				jsongeshi = json.dumps(d, indent=4, ensure_ascii=False)
			# print(jsongeshi)
			jsonfile.write(jsongeshi)
			if j != all_numbers:
				jsonfile.write(",")
			j = j + 1
		jsonfile.write("]")
		csvfile = open(csvpath, 'r', encoding='utf-8')
		mysql_create(csvfile)
		mysql_write(csvfile)
	language_adds_flag=0



if __name__ == '__main__':
	global a
	a = 0
	spider()

# if __name__ == '__main__':
# 	schedule.every(20).minutes.do(spider)
# 	while True:
# 		try:
# 			schedule.run_pending()
# 			time.sleep(1)
# 		except:
# 			print("error")